#include "StdAfx.h"
#include "Thread.h"

template<class T, DWORD(T::*mem_fun)()> 
inline DWORD WINAPI thread_thunk(void* p) 
{ 
  return (static_cast<T*>(p)->*mem_fun)();
}

CThread::CThread(DWORD dwThreadWaitTime)
  : m_hThread(NULL), m_dwThreadID(0)
  , m_bTerminate(false), m_dwThreadWaitTime(dwThreadWaitTime)
{
  ::InitializeCriticalSection(&m_csSync);
}

CThread::~CThread(void)
{
  Stop();
  ::DeleteCriticalSection(&m_csSync);
}

bool CThread::Run()
{
  if (m_hThread != NULL)
    return true;

  m_bTerminate = false;
  m_hThread = ::CreateThread(NULL, 0, thread_thunk<CThread, &CThread::ThreadMainHndlr>, this, 0, &m_dwThreadID);
  return m_hThread != NULL;
}

void CThread::Stop()
{
  if (m_hThread == NULL)
    return;

  SyncSet(m_bTerminate, true);

  WaitForSingleObject(m_hThread, m_dwThreadWaitTime);
  m_hThread = NULL;
  m_dwThreadID = 0;
}

DWORD CThread::ThreadMainHndlr()
{
  DWORD res = this->ThreadMain();

  m_bTerminate = true;
  m_hThread = NULL;
  m_dwThreadID = 0;

  return res;
}
